Remove gtk_dialog_run()
authorEmmanuele Bassi <ebassi@gnome.org>
Thu, 30 Apr 2020 17:53:02 +0000 (18:53 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Tue, 12 May 2020 12:45:15 +0000 (13:45 +0100)
Nested main loops are bad, as they introduce layers of complexity caused
by the potential re-entrancy in the case of multiple event sources, like
IPC, threads, etc. Additionally, the programming model they provide—stop
the world while spinning a new loop—does not conform to the event-driven
model employed by GTK.

docs/reference/gtk/gtk4-sections.txt
gtk/gtkdialog.c
gtk/gtkdialog.h

index 68c436cf8480f580acebb2ace38b90291b3f9102..1daaa1ad22f8328da6c0a2d95143ad50a6a9c05c 100644 (file)
@@ -678,7 +678,6 @@ GtkDialogFlags
 GtkResponseType
 gtk_dialog_new
 gtk_dialog_new_with_buttons
-gtk_dialog_run
 gtk_dialog_response
 gtk_dialog_add_button
 gtk_dialog_add_buttons
index bab86685aa42471e2c28869714d2c0dd34b67061..f5c401311a0c66623db17b72caa2ae9dd5e45eb5 100644 (file)
  * a dialog receives a delete event, the #GtkDialog::response signal will
  * be emitted with a response ID of #GTK_RESPONSE_DELETE_EVENT.
  *
- * If you want to block waiting for a dialog to return before returning
- * control flow to your code, you can call gtk_dialog_run(). This function
- * enters a recursive main loop and waits for the user to respond to the
- * dialog, returning the response ID corresponding to the button the user
- * clicked.
- *
  * For the simple dialog in the following example, in reality you’d probably
  * use #GtkMessageDialog to save yourself some effort. But you’d need to
  * create the dialog contents manually if you had more than a simple message
@@ -592,7 +586,6 @@ gtk_dialog_buildable_interface_init (GtkBuildableIface *iface)
 static gboolean
 gtk_dialog_close_request (GtkWindow *window)
 {
-  /* emit response signal, this will shut down the loop if we are in gtk_dialog_run */
   gtk_dialog_response (GTK_DIALOG (window), GTK_RESPONSE_DELETE_EVENT);
 
   return GTK_WINDOW_CLASS (gtk_dialog_parent_class)->close_request (window);
@@ -1011,9 +1004,8 @@ gtk_dialog_set_default_response (GtkDialog *dialog,
  * @response_id: response ID
  *
  * Emits the #GtkDialog::response signal with the given response ID.
- * Used to indicate that the user has responded to the dialog in some way;
- * typically either you or gtk_dialog_run() will be monitoring the
- * ::response signal and take appropriate action.
+ *
+ * Used to indicate that the user has responded to the dialog in some way.
  **/
 void
 gtk_dialog_response (GtkDialog *dialog,
@@ -1027,166 +1019,6 @@ gtk_dialog_response (GtkDialog *dialog,
                 response_id);
 }
 
-typedef struct
-{
-  GtkDialog *dialog;
-  gint response_id;
-  GMainLoop *loop;
-  gboolean destroyed;
-} RunInfo;
-
-static void
-shutdown_loop (RunInfo *ri)
-{
-  if (g_main_loop_is_running (ri->loop))
-    g_main_loop_quit (ri->loop);
-}
-
-static void
-run_unmap_handler (GtkDialog *dialog, gpointer data)
-{
-  RunInfo *ri = data;
-
-  shutdown_loop (ri);
-}
-
-static void
-run_response_handler (GtkDialog *dialog,
-                      gint response_id,
-                      gpointer data)
-{
-  RunInfo *ri;
-
-  ri = data;
-
-  ri->response_id = response_id;
-
-  shutdown_loop (ri);
-}
-
-static void
-run_destroy_handler (GtkDialog *dialog, gpointer data)
-{
-  RunInfo *ri = data;
-
-  /* shutdown_loop will be called by run_unmap_handler */
-
-  ri->destroyed = TRUE;
-}
-
-/**
- * gtk_dialog_run:
- * @dialog: a #GtkDialog
- *
- * Blocks in a recursive main loop until the @dialog either emits the
- * #GtkDialog::response signal, or is destroyed. If the dialog is
- * destroyed during the call to gtk_dialog_run(), gtk_dialog_run() returns
- * #GTK_RESPONSE_NONE. Otherwise, it returns the response ID from the
- * ::response signal emission.
- *
- * Before entering the recursive main loop, gtk_dialog_run() calls
- * gtk_widget_show() on the dialog for you. Note that you still
- * need to show any children of the dialog yourself.
- *
- * During gtk_dialog_run(), the default behavior of delete events
- * is disabled; if the dialog receives a delete event, it will not be
- * destroyed as windows usually are, and gtk_dialog_run() will return
- * #GTK_RESPONSE_DELETE_EVENT. Also, during gtk_dialog_run() the dialog
- * will be modal. You can force gtk_dialog_run() to return at any time by
- * calling gtk_dialog_response() to emit the ::response signal. Destroying
- * the dialog during gtk_dialog_run() is a very bad idea, because your
- * post-run code won’t know whether the dialog was destroyed or not.
- *
- * After gtk_dialog_run() returns, you are responsible for hiding or
- * destroying the dialog if you wish to do so.
- *
- * Typical usage of this function might be:
- * |[<!-- language="C" -->
- *   GtkWidget *dialog = gtk_dialog_new ();
- *   // Set up dialog...
- *
- *   int result = gtk_dialog_run (GTK_DIALOG (dialog));
- *   switch (result)
- *     {
- *       case GTK_RESPONSE_ACCEPT:
- *          // do_application_specific_something ();
- *          break;
- *       default:
- *          // do_nothing_since_dialog_was_cancelled ();
- *          break;
- *     }
- *   gtk_window_destroy (dialog);
- * ]|
- *
- * Note that even though the recursive main loop gives the effect of a
- * modal dialog (it prevents the user from interacting with other
- * windows in the same window group while the dialog is run), callbacks
- * such as timeouts, IO channel watches, DND drops, etc, will
- * be triggered during a gtk_dialog_run() call.
- *
- * Returns: response ID
- **/
-gint
-gtk_dialog_run (GtkDialog *dialog)
-{
-  RunInfo ri = { NULL, GTK_RESPONSE_NONE, NULL, FALSE };
-  gboolean was_modal;
-  gboolean was_hide_on_close;
-  gulong response_handler;
-  gulong unmap_handler;
-  gulong destroy_handler;
-
-  g_return_val_if_fail (GTK_IS_DIALOG (dialog), -1);
-
-  g_object_ref (dialog);
-
-  was_modal = gtk_window_get_modal (GTK_WINDOW (dialog));
-  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-  was_hide_on_close = gtk_window_get_hide_on_close (GTK_WINDOW (dialog));
-  gtk_window_set_hide_on_close (GTK_WINDOW (dialog), TRUE);
-
-  if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
-    gtk_widget_show (GTK_WIDGET (dialog));
-
-  response_handler =
-    g_signal_connect (dialog,
-                      "response",
-                      G_CALLBACK (run_response_handler),
-                      &ri);
-
-  unmap_handler =
-    g_signal_connect (dialog,
-                      "unmap",
-                      G_CALLBACK (run_unmap_handler),
-                      &ri);
-
-  destroy_handler =
-    g_signal_connect (dialog,
-                      "destroy",
-                      G_CALLBACK (run_destroy_handler),
-                      &ri);
-
-  ri.loop = g_main_loop_new (NULL, FALSE);
-  g_main_loop_run (ri.loop);
-  g_main_loop_unref (ri.loop);
-
-  ri.loop = NULL;
-
-  if (!ri.destroyed)
-    {
-      gtk_window_set_modal (GTK_WINDOW (dialog), was_modal);
-      gtk_window_set_hide_on_close (GTK_WINDOW (dialog), was_hide_on_close);
-
-      g_signal_handler_disconnect (dialog, response_handler);
-      g_signal_handler_disconnect (dialog, unmap_handler);
-      g_signal_handler_disconnect (dialog, destroy_handler);
-    }
-
-  g_object_unref (dialog);
-
-  return ri.response_id;
-}
-
 /**
  * gtk_dialog_get_widget_for_response:
  * @dialog: a #GtkDialog
index 056253041d3d3614a81d7437453ec5c190cd1d60..b6530176615d4b4cfe289f26515a7f05cc6c98de 100644 (file)
@@ -176,10 +176,6 @@ GDK_AVAILABLE_IN_ALL
 void gtk_dialog_response           (GtkDialog *dialog,
                                     gint       response_id);
 
-/* Returns response_id */
-GDK_AVAILABLE_IN_ALL
-gint gtk_dialog_run                (GtkDialog *dialog);
-
 GDK_AVAILABLE_IN_ALL
 GtkWidget * gtk_dialog_get_content_area (GtkDialog *dialog);
 GDK_AVAILABLE_IN_ALL